/*
 * @Date: 2023-02-12 18:58:30
 * @LastEditors: Zireael 1193875164@qq.com
 * @LastEditTime: 2023-04-05 12:17:29
 * @FilePath: \A19\backend\src\utils\messageImplement.ts
 */
import { MsgTeacherJoin } from './../shared/protocols/AMessages/Test/MsgTeacherJoin';
/*
 * @Date: 2023-02-12 18:58:30
 * @LastEditors: Zireael 1193875164@qq.com
 * @LastEditTime: 2023-02-23 19:24:46
 * @FilePath: \A19\backend\src\utils\messageImplement.ts
 */
import { Test } from './Classes/Test';
import { MsgCall, WsServer, WsConnection } from 'tsrpc';
import { ServiceType } from '../shared/protocols/serviceProto';
import { MsgJoinTest } from '../shared/protocols/AMessages/Test/MsgJoinTest';
import { MsgRTCConn } from '../shared/protocols/AMessages/RTC/MsgRTCConn';
// import { test } from 'mocha';
// import { isGeneratorFunction } from 'util/types';
// import { MsgStudentStatus } from '../shared/protocols/AMessages/Test/MsgStudentStatus';
import { MsgTeacherStatus } from '../shared/protocols/AMessages/Test/MsgTeacherStatus';
// import { ObjectId } from 'mongodb';
import { MsgStartLive } from '../shared/protocols/AMessages/Live/MsgStartLive';
import { Live } from './Classes/Live';
import { Global } from '../Global/index';
import { MsgStuStatus } from '../shared/protocols/AMessages/Live/MsgStuStatus';
import { MsgLiveTarget } from '../shared/protocols/AMessages/Live/MsgLiveTarget';
import { MsgLiveConn } from '../shared/protocols/AMessages/Live/MsgLiveConn';
import { users } from '../shared/types/user';
import { Wsserver } from '../index';
import { courses } from '../shared/types/courses';

export function messageImplement(wsserver: WsServer<ServiceType>) {

    //test
    wsserver.listenMsg('AMessages/Test/JoinTest',async (call:MsgCall<MsgJoinTest, any>) => {
        console.log(call.msg.student.toString()," join");
        
        const res = await Test.joinTest(call.msg,call.conn as WsConnection)
        if(res === 'unexist' || res === 'sunexist'){
            call.conn.sendMsg('AMessages/Test/ConnectFailed',{
                message:res
            })
            return 
        }
        
        call.conn.sendMsg('AMessages/Test/TeacherStatus',{
            status:res? 'connected' : 'disconnected'
        }as MsgTeacherStatus)

        return 
    })

    wsserver.listenMsg('AMessages/Test/TeacherJoin',(call:MsgCall<MsgTeacherJoin,any>) =>{
        
        Test.teacherJoin(call.msg,call.conn as WsConnection)
        return
    })

    wsserver.listenMsg('AMessages/RTC/RTCConn',async call =>{
        const test = Test.tests.find(test => call.msg.testId.equals(test._id))
        if(test === undefined) return

        if(call.msg.type === 'video-offer'){
            let target = call.msg.target

            if(target === undefined){
                //分配算法...
                target = test.getTarget(call.msg.origin)

                call.msg.target = target
                //告诉这个新加入的节点 target是谁
                await call.conn.sendMsg('AMessages/RTC/SendTarget',{
                    target
                })
                
            }
            await test?.teacher?.connection.sendMsg('AMessages/RTC/RTCConn', call.msg as MsgRTCConn)
        }
        else if(call.msg.type === 'video-answer'){
            const target = call.msg.target
            if(target === undefined) return

            test?.students.forEach(async (value, key, map)=>{
                if(target.equals(value.student._id)){
                    await value.connection.sendMsg('AMessages/RTC/RTCConn',call.msg as MsgRTCConn)
                }
            })
            // student?.connection.sendMsg('AMessages/RTC/RTCConn',{
            //     ...call.msg,
            // })
        }
        else if(call.msg.type === 'new-ice-candidate'){
            const target = call.msg.target
            if(target === undefined) return
            
            if(test?.teacher?.teacher._id.equals(target)){
                //目的端为教师端
                await test?.teacher?.connection.sendMsg('AMessages/RTC/RTCConn', call.msg as MsgRTCConn)
            }
            else{
                test?.students.forEach(async (value, key, map)=>{
                    if(target.equals(value.student._id)){
                        await value.connection.sendMsg('AMessages/RTC/RTCConn',call.msg as MsgRTCConn)
                    }
                })
            }

        }
    })

    wsserver.listenMsg('AMessages/RTC/TestConn',call =>{
        const test = Test.tests.find(test => test._id.equals(call.msg.test))
        if(!test) return
        const student = [...test.students.values()].find(stu => stu.student._id.equals(call.msg.student))
        if(!student) return
        (student.connection as WsConnection<ServiceType>).sendMsg('AMessages/RTC/TestConn',call.msg)
    })

    wsserver.listenMsg('AMessages/Test/Warn',call =>{
        const test = Test.tests.find(test => test._id.equals(call.msg.test))
        if(!test) return

        const target = call.msg.target

        if(target){
            //单播
            const stus = [...test.students.values()]
            const stu = stus.find(s => s.student._id.equals(target))
            if(!stu) return

            stu.connection.sendMsg('AMessages/Test/Warn',call.msg)
        }
        else{
            //广播
            const connections = [...test.students.values()].map(s => s.connection)
            wsserver.broadcastMsg('AMessages/Test/Warn',call.msg,connections)
        }
        
    })

    //#region 
    // wsserver.listenMsg('AMessages/RTC/AskConn',call =>{
    //     const test = Test.tests.find(test => test._id.equals(call.msg.testId))
    //     if(!test) return
    //     const conns = new Array<WsConnection<ServiceType>>()
    //     // call.msg.students.forEach(s =>{
    //     //     const student = test.students.get(s._id.toString())
    //     //     if(student) conns.push(student.connection)
    //     // })

    //     Wsserver.broadcastMsg('AMessages/Test/TeacherStatus',{
    //         status:'connected'
    //     },[...test.students.values()].map(student=>student.connection))
    // })
    //#endregion

    //live
    wsserver.listenMsg('AMessages/Live/StartLive',async (call:MsgCall<MsgStartLive, any>) =>{
        const teacher = await Global.collection('users').findOne({
            _id:call.msg.teacher
        })
        if(teacher === null) return
        new Live(call.msg.courseId,{
            connection: call.conn as WsConnection,
            teacher
        })
    })

    wsserver.listenMsg('AMessages/Live/StuStatus',async (call:MsgCall<MsgStuStatus,any>) =>{
        const live = Live.lives.find(live => live.courseId.equals(call.msg.course))
        if(live === undefined) {
            call.conn.sendMsg('AMessages/Live/LiveEnd',{})//直播已结束
            return 
        }
        

        const studentId = call.msg.student
        const stu = live.students.find(student => student._id.equals(studentId));
        await (call.conn as WsConnection<ServiceType>).sendMsg('AMessages/Communicate/InitComm',{
            talks:live.talks
        }).then().catch(error =>{
            if(error instanceof Error)
            console.log(error.message);
        })
        if(call.msg.status === 'connect'){
            //通知某个节点连接这个客户端
            
            // console.log(stu);
            if(stu === undefined) return //没有这个学生 没选这个课

            await (call.conn as WsConnection<ServiceType>).sendMsg('AMessages/Live/StuList',{
                students:live.students,
                course:live.courseInfo as courses
            })

            stu.status = 'online'
            stu.connection = call.conn as WsConnection
            const target = live.getTarget(stu._id,call.conn as WsConnection)
            // console.log(live.connectionMap);
            await target.sendMsg('AMessages/Live/LiveTarget',{
                target:studentId
            } as MsgLiveTarget)

            // live.host.connection.sendMsg('AMessages/Live/StuStatus',{
            //     student:stu._id,
            //     course:live.courseId,
            //     status:'connect'
            // } as MsgStuStatus)
            const connections = new Array<WsConnection>
            connections.push(live.host.connection)
            live.students.forEach(s =>{
                if(s.connection){
                    connections.push(s.connection)
                }
            })
            
            await Wsserver.broadcastMsg('AMessages/Live/StuStatus',{
                student:stu._id,
                course:live.courseId,
                status:'connect'
            },connections)
        }
        else{
            
        }
        if(stu)
            await live.sendTalk(stu as users,call.msg.status === 'connect'?"加入课堂":"离开课堂",call.msg.status)
    })

    wsserver.listenMsg('AMessages/Live/LiveConn',async (call:MsgCall<MsgLiveConn,any>)=>{
        const live = Live.lives.find(live => live.courseId.equals(call.msg.courseId))
        if(live === undefined) {
            call.conn.sendMsg('AMessages/Live/LiveEnd',{})//直播已结束
            return 
        }

        const target = call.msg.target
        if(call.msg.type === 'video-offer'){

            if(call.msg.target.equals(live.host.teacher._id)){
                console.log('talk channel');
                live.host.connection.sendMsg('AMessages/Live/LiveConn',call.msg)
                return
            }

            const student = live.students.find(student => student._id.equals(target))
            // console.log(student);
            if(student?.status === 'offline') return
            student?.connection?.sendMsg('AMessages/Live/LiveConn',call.msg)
        }
        else{
            if(target.equals(live.host.teacher._id)){
                live.host.connection.sendMsg('AMessages/Live/LiveConn',call.msg)
            }
            else{
                const student = live.students.find(student => student._id.equals(target))
                student?.connection?.sendMsg('AMessages/Live/LiveConn',call.msg)
            }
        }
        // else if(call.msg.type === 'video-answer'){
        //     if(target.equals(live.host.teacher._id)){
        //         live.host.connection.sendMsg('AMessages/Live/LiveConn',call.msg)
        //     }
        //     else{
        //         const student = live.students.find(student => student._id.equals(target))
        //         student?.connection?.sendMsg('AMessages/Live/LiveConn',call.msg)
        //     }
        // }
        // else if(call.msg.type === 'new-ice-candidate'){
        //     if(target.equals(live.host.teacher._id)){
        //         live.host.connection.sendMsg('AMessages/Live/LiveConn',call.msg)
        //     }
        //     else{
        //         const student = live.students.find(student => student._id.equals(target))
        //         student?.connection?.sendMsg('AMessages/Live/LiveConn',call.msg)
        //     }
        // }
    })
}